/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.hpvas.persistence.dao;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import edu.hpvas.persistence.entity.Appointment;
import edu.hpvas.persistence.entity.MedicalRecord;
import java.util.ArrayList;
import java.util.Collection;
import edu.hpvas.persistence.entity.Pet;
import edu.hpvas.persistence.entity.Vaccine;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 *
 * @author raider
 */
public class MedicalRecordDAO implements Serializable {

    public MedicalRecordDAO() {
        this.emf = Persistence.createEntityManagerFactory("HPVAS");
    }
    private EntityManagerFactory emf;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(MedicalRecord medicalRecord) throws Exception {
        if (medicalRecord.getAppointmentCollection() == null) {
            medicalRecord.setAppointmentCollection(new ArrayList<Appointment>());
        }
        if (medicalRecord.getPetCollection() == null) {
            medicalRecord.setPetCollection(new ArrayList<Pet>());
        }
        if (medicalRecord.getVaccineCollection() == null) {
            medicalRecord.setVaccineCollection(new ArrayList<Vaccine>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Appointment> attachedAppointmentCollection = new ArrayList<Appointment>();
            for (Appointment appointmentCollectionAppointmentToAttach : medicalRecord.getAppointmentCollection()) {
                appointmentCollectionAppointmentToAttach = em.getReference(appointmentCollectionAppointmentToAttach.getClass(), appointmentCollectionAppointmentToAttach.getId());
                attachedAppointmentCollection.add(appointmentCollectionAppointmentToAttach);
            }
            medicalRecord.setAppointmentCollection(attachedAppointmentCollection);
            Collection<Pet> attachedPetCollection = new ArrayList<Pet>();
            for (Pet petCollectionPetToAttach : medicalRecord.getPetCollection()) {
                petCollectionPetToAttach = em.getReference(petCollectionPetToAttach.getClass(), petCollectionPetToAttach.getId());
                attachedPetCollection.add(petCollectionPetToAttach);
            }
            medicalRecord.setPetCollection(attachedPetCollection);
            Collection<Vaccine> attachedVaccineCollection = new ArrayList<Vaccine>();
            for (Vaccine vaccineCollectionVaccineToAttach : medicalRecord.getVaccineCollection()) {
                vaccineCollectionVaccineToAttach = em.getReference(vaccineCollectionVaccineToAttach.getClass(), vaccineCollectionVaccineToAttach.getId());
                attachedVaccineCollection.add(vaccineCollectionVaccineToAttach);
            }
            medicalRecord.setVaccineCollection(attachedVaccineCollection);
            em.persist(medicalRecord);
            for (Appointment appointmentCollectionAppointment : medicalRecord.getAppointmentCollection()) {
                MedicalRecord oldIdMedicalRecordOfAppointmentCollectionAppointment = appointmentCollectionAppointment.getIdMedicalRecord();
                appointmentCollectionAppointment.setIdMedicalRecord(medicalRecord);
                appointmentCollectionAppointment = em.merge(appointmentCollectionAppointment);
                if (oldIdMedicalRecordOfAppointmentCollectionAppointment != null) {
                    oldIdMedicalRecordOfAppointmentCollectionAppointment.getAppointmentCollection().remove(appointmentCollectionAppointment);
                    oldIdMedicalRecordOfAppointmentCollectionAppointment = em.merge(oldIdMedicalRecordOfAppointmentCollectionAppointment);
                }
            }
            for (Pet petCollectionPet : medicalRecord.getPetCollection()) {
                MedicalRecord oldIdMedicalRecordOfPetCollectionPet = petCollectionPet.getIdMedicalRecord();
                petCollectionPet.setIdMedicalRecord(medicalRecord);
                petCollectionPet = em.merge(petCollectionPet);
                if (oldIdMedicalRecordOfPetCollectionPet != null) {
                    oldIdMedicalRecordOfPetCollectionPet.getPetCollection().remove(petCollectionPet);
                    oldIdMedicalRecordOfPetCollectionPet = em.merge(oldIdMedicalRecordOfPetCollectionPet);
                }
            }
            for (Vaccine vaccineCollectionVaccine : medicalRecord.getVaccineCollection()) {
                MedicalRecord oldIdMedicalRecordOfVaccineCollectionVaccine = vaccineCollectionVaccine.getIdMedicalRecord();
                vaccineCollectionVaccine.setIdMedicalRecord(medicalRecord);
                vaccineCollectionVaccine = em.merge(vaccineCollectionVaccine);
                if (oldIdMedicalRecordOfVaccineCollectionVaccine != null) {
                    oldIdMedicalRecordOfVaccineCollectionVaccine.getVaccineCollection().remove(vaccineCollectionVaccine);
                    oldIdMedicalRecordOfVaccineCollectionVaccine = em.merge(oldIdMedicalRecordOfVaccineCollectionVaccine);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findMedicalRecord(medicalRecord.getId()) != null) {
                System.out.println("MedicalRecord " + medicalRecord + " already exists.");
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(MedicalRecord medicalRecord) throws Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            MedicalRecord persistentMedicalRecord = em.find(MedicalRecord.class, medicalRecord.getId());
            Collection<Appointment> appointmentCollectionOld = persistentMedicalRecord.getAppointmentCollection();
            Collection<Appointment> appointmentCollectionNew = medicalRecord.getAppointmentCollection();
            Collection<Pet> petCollectionOld = persistentMedicalRecord.getPetCollection();
            Collection<Pet> petCollectionNew = medicalRecord.getPetCollection();
            Collection<Vaccine> vaccineCollectionOld = persistentMedicalRecord.getVaccineCollection();
            Collection<Vaccine> vaccineCollectionNew = medicalRecord.getVaccineCollection();
            Collection<Appointment> attachedAppointmentCollectionNew = new ArrayList<Appointment>();
            for (Appointment appointmentCollectionNewAppointmentToAttach : appointmentCollectionNew) {
                appointmentCollectionNewAppointmentToAttach = em.getReference(appointmentCollectionNewAppointmentToAttach.getClass(), appointmentCollectionNewAppointmentToAttach.getId());
                attachedAppointmentCollectionNew.add(appointmentCollectionNewAppointmentToAttach);
            }
            appointmentCollectionNew = attachedAppointmentCollectionNew;
            medicalRecord.setAppointmentCollection(appointmentCollectionNew);
            Collection<Pet> attachedPetCollectionNew = new ArrayList<Pet>();
            for (Pet petCollectionNewPetToAttach : petCollectionNew) {
                petCollectionNewPetToAttach = em.getReference(petCollectionNewPetToAttach.getClass(), petCollectionNewPetToAttach.getId());
                attachedPetCollectionNew.add(petCollectionNewPetToAttach);
            }
            petCollectionNew = attachedPetCollectionNew;
            medicalRecord.setPetCollection(petCollectionNew);
            Collection<Vaccine> attachedVaccineCollectionNew = new ArrayList<Vaccine>();
            for (Vaccine vaccineCollectionNewVaccineToAttach : vaccineCollectionNew) {
                vaccineCollectionNewVaccineToAttach = em.getReference(vaccineCollectionNewVaccineToAttach.getClass(), vaccineCollectionNewVaccineToAttach.getId());
                attachedVaccineCollectionNew.add(vaccineCollectionNewVaccineToAttach);
            }
            vaccineCollectionNew = attachedVaccineCollectionNew;
            medicalRecord.setVaccineCollection(vaccineCollectionNew);
            medicalRecord = em.merge(medicalRecord);
            for (Appointment appointmentCollectionOldAppointment : appointmentCollectionOld) {
                if (!appointmentCollectionNew.contains(appointmentCollectionOldAppointment)) {
                    appointmentCollectionOldAppointment.setIdMedicalRecord(null);
                    appointmentCollectionOldAppointment = em.merge(appointmentCollectionOldAppointment);
                }
            }
            for (Appointment appointmentCollectionNewAppointment : appointmentCollectionNew) {
                if (!appointmentCollectionOld.contains(appointmentCollectionNewAppointment)) {
                    MedicalRecord oldIdMedicalRecordOfAppointmentCollectionNewAppointment = appointmentCollectionNewAppointment.getIdMedicalRecord();
                    appointmentCollectionNewAppointment.setIdMedicalRecord(medicalRecord);
                    appointmentCollectionNewAppointment = em.merge(appointmentCollectionNewAppointment);
                    if (oldIdMedicalRecordOfAppointmentCollectionNewAppointment != null && !oldIdMedicalRecordOfAppointmentCollectionNewAppointment.equals(medicalRecord)) {
                        oldIdMedicalRecordOfAppointmentCollectionNewAppointment.getAppointmentCollection().remove(appointmentCollectionNewAppointment);
                        oldIdMedicalRecordOfAppointmentCollectionNewAppointment = em.merge(oldIdMedicalRecordOfAppointmentCollectionNewAppointment);
                    }
                }
            }
            for (Pet petCollectionOldPet : petCollectionOld) {
                if (!petCollectionNew.contains(petCollectionOldPet)) {
                    petCollectionOldPet.setIdMedicalRecord(null);
                    petCollectionOldPet = em.merge(petCollectionOldPet);
                }
            }
            for (Pet petCollectionNewPet : petCollectionNew) {
                if (!petCollectionOld.contains(petCollectionNewPet)) {
                    MedicalRecord oldIdMedicalRecordOfPetCollectionNewPet = petCollectionNewPet.getIdMedicalRecord();
                    petCollectionNewPet.setIdMedicalRecord(medicalRecord);
                    petCollectionNewPet = em.merge(petCollectionNewPet);
                    if (oldIdMedicalRecordOfPetCollectionNewPet != null && !oldIdMedicalRecordOfPetCollectionNewPet.equals(medicalRecord)) {
                        oldIdMedicalRecordOfPetCollectionNewPet.getPetCollection().remove(petCollectionNewPet);
                        oldIdMedicalRecordOfPetCollectionNewPet = em.merge(oldIdMedicalRecordOfPetCollectionNewPet);
                    }
                }
            }
            for (Vaccine vaccineCollectionOldVaccine : vaccineCollectionOld) {
                if (!vaccineCollectionNew.contains(vaccineCollectionOldVaccine)) {
                    vaccineCollectionOldVaccine.setIdMedicalRecord(null);
                    vaccineCollectionOldVaccine = em.merge(vaccineCollectionOldVaccine);
                }
            }
            for (Vaccine vaccineCollectionNewVaccine : vaccineCollectionNew) {
                if (!vaccineCollectionOld.contains(vaccineCollectionNewVaccine)) {
                    MedicalRecord oldIdMedicalRecordOfVaccineCollectionNewVaccine = vaccineCollectionNewVaccine.getIdMedicalRecord();
                    vaccineCollectionNewVaccine.setIdMedicalRecord(medicalRecord);
                    vaccineCollectionNewVaccine = em.merge(vaccineCollectionNewVaccine);
                    if (oldIdMedicalRecordOfVaccineCollectionNewVaccine != null && !oldIdMedicalRecordOfVaccineCollectionNewVaccine.equals(medicalRecord)) {
                        oldIdMedicalRecordOfVaccineCollectionNewVaccine.getVaccineCollection().remove(vaccineCollectionNewVaccine);
                        oldIdMedicalRecordOfVaccineCollectionNewVaccine = em.merge(oldIdMedicalRecordOfVaccineCollectionNewVaccine);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = medicalRecord.getId();
                if (findMedicalRecord(id) == null) {
                    System.out.println("The medicalRecord with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id){
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            MedicalRecord medicalRecord = null;
            try {
                medicalRecord = em.getReference(MedicalRecord.class, id);
                medicalRecord.getId();
            } catch (EntityNotFoundException enfe) {
                System.out.println("The medicalRecord with id " + id + " no longer exists.");
            }
            Collection<Appointment> appointmentCollection = medicalRecord.getAppointmentCollection();
            for (Appointment appointmentCollectionAppointment : appointmentCollection) {
                appointmentCollectionAppointment.setIdMedicalRecord(null);
                appointmentCollectionAppointment = em.merge(appointmentCollectionAppointment);
            }
            Collection<Pet> petCollection = medicalRecord.getPetCollection();
            for (Pet petCollectionPet : petCollection) {
                petCollectionPet.setIdMedicalRecord(null);
                petCollectionPet = em.merge(petCollectionPet);
            }
            Collection<Vaccine> vaccineCollection = medicalRecord.getVaccineCollection();
            for (Vaccine vaccineCollectionVaccine : vaccineCollection) {
                vaccineCollectionVaccine.setIdMedicalRecord(null);
                vaccineCollectionVaccine = em.merge(vaccineCollectionVaccine);
            }
            em.remove(medicalRecord);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<MedicalRecord> findMedicalRecordEntities() {
        return findMedicalRecordEntities(true, -1, -1);
    }

    public List<MedicalRecord> findMedicalRecordEntities(int maxResults, int firstResult) {
        return findMedicalRecordEntities(false, maxResults, firstResult);
    }

    private List<MedicalRecord> findMedicalRecordEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(MedicalRecord.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public MedicalRecord findMedicalRecord(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(MedicalRecord.class, id);
        } finally {
            em.close();
        }
    }

    public int getMedicalRecordCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<MedicalRecord> rt = cq.from(MedicalRecord.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
